package com.alogic.validator.impl.pwd;

import com.alogic.validator.Validator;
import com.anysoft.util.BaseException;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;


/**
 * 连续键盘
 *
 * @version 1.6.13.25 [20201110 duanyy] <br>
 * - 修复validator的问题
 */
public class ContKeyboard extends Validator.Abstract{
    protected boolean exclude = true;
    protected boolean qwe = true;
    protected boolean qaz = false;
    protected static final Map<Character,Character> keyMapping = new HashMap<Character,Character>();
    static{
        keyMapping.put('!','1');
        keyMapping.put('@','2');
        keyMapping.put('#','3');
        keyMapping.put('$','4');
        keyMapping.put('%','5');
        keyMapping.put('^','6');
        keyMapping.put('&','7');
        keyMapping.put('*','8');
        keyMapping.put('(','9');
        keyMapping.put(')','0');
        keyMapping.put('_','-');
        keyMapping.put('+','=');
    }

    protected static final char[][] keyCode = {
            {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='},
            {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'},
            {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'},
            {'z', 'x', 'c', 'v', 'b', 'n', 'm'}
    };
    @Override
    public void configure(Properties p) {
        super.configure(p);
        exclude = PropertiesConstants.getBoolean(p,"exclude",exclude,true);
        qwe = PropertiesConstants.getBoolean(p,"qwe",qwe,true);
        qaz = PropertiesConstants.getBoolean(p,"qaz",qaz,true);
    }

    @Override
    public boolean check(String value, Properties ctx,boolean throwException) {
        boolean result = exclude?!isContinuous(value):isContinuous(value);
        if (!result && throwException){
            throw new BaseException(getCode(ctx),getMessage(ctx));
        }
        return result;
    }

    @Override
    public boolean check(String value, Properties ctx, Listener listener) {
        boolean result = exclude?!isContinuous(value):isContinuous(value);
        if (listener != null){
            listener.result(result,value,this,ctx);
        }
        return result;
    }

    protected boolean isContinuous(String str) {
        if (StringUtils.isEmpty(str)){
            return false;
        }
        char[] c = str.toCharArray();
        int length = c.length;
        int [] x = new int[length];
        int [] y = new int[length];
        for (int i = 0; i < length; i++) {
            toHere:
            for (int j = 0; j < keyCode.length; j++) {
                for (int k = 0; k < keyCode[j].length; k++) {
                    if (toLowercase(c[i]) == keyCode[j][k]) {
                        x[i] = j;
                        y[i] = k;
                        break toHere;
                    }
                }
            }
        }
        for (int i = 0; i < length - 2; i++) {
            if (x[i] == x[i+1] && x[i+1] == x[i+2]){// 连续三个字符在同一行上
                if (qwe){
                    if (isContinuous(y[i],y[i+1],y[i+2])){ // 连续的值
                        return true;
                    }
                }
            }
            if (y[i] == y[i+1] && y[i+1] == y[i+2]){ //连续三个字符在同一列
                if (qaz){
                    if (isContinuous(x[i],x[i+1],x[i+2])){ // 连续的值
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static boolean isContinuous(int a,int b,int c){
        return (a + 1 == b && a + 2 == c) || (a - 1 == b && a - 2 == c);
    }

    public static char toLowercase(char ch){
        Character found = keyMapping.get(ch);
        return found == null ? Character.toLowerCase(ch):found;
    }
}
